package helper

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/validation"
)

func MD5(str string) string {
	md5Ctx := md5.New()
	md5Ctx.Write([]byte(str))
	return hex.EncodeToString(md5Ctx.Sum(nil))
}

func ValidParams(param interface{},kmp map[string]string) string {
	valid := validation.Validation{RequiredFirst: true}

	b, err := valid.Valid(param)
	if err != nil {
		return err.Error()
	}
	if !b {
		for _, err := range valid.Errors {
			return kmp[err.Field]+err.Message
		}
	}
	return ""
}

//InterfaceToJSON 将interface数据转json
func InterfaceToJSON(itf interface{}) (string, error) {
	b, err := json.Marshal(&itf)
	return string(b), err
}

//InterfaceToInt interface转整型
func InterfaceToInt(itf interface{}) (num int, err error) {
	return strconv.Atoi(fmt.Sprintf("%v", itf))
}

//UpperFirst 首字母大写
func UpperFirst(str string) string {
	return strings.Replace(str, str[0:1], strings.ToUpper(str[0:1]), 1)
}

//Path2Map 把url路径中的path请求，变成key val，path参数值形式：/user/list/p/1，转成map[string]string
func Path2Map(path string) map[string]string {
	var data = make(map[string]string)
	path = strings.Trim(path, "/")
	slice := strings.Split(path, "/")
	cnt := len(slice)
	if cnt%2 == 1 {
		cnt = cnt - 1
	}
	if cnt > 0 {
		for i := 0; i < cnt; {
			data[slice[i]] = slice[(i + 1)]
			i = i + 2
		}
	}
	return data
}

//Query2Map 把url中的query请求参数变成key val，query参数形式：p=1&listRows=10&aaa=bbb，转成map[string]string
func Query2Map(query string) map[string]string {
	var data = make(map[string]string)
	query = strings.Trim(query, "=&")
	slice := strings.Split(query, "&")
	if len(slice) > 0 {
		for _, v := range slice {
			vv := strings.Split(v, "=")
			if len(vv) == 2 {
				data[vv[0]] = data[vv[1]]
			}
		}
	}
	return data
}

// Logger is used to write logs in goroutine
// 在协程中记录日志
func Logger(str string, note string) {
	go func() {
		path := beego.AppConfig.String("log_path")
		if path == "" {
			path = "./logs"
		}

		if note == "" {
			note = "write"
		}

		currentTime := time.Now().Local()
		logTmp := currentTime.Format("2006-01-02 15:04:05 ") + str + "\r\n"
		daily := currentTime.Format("2006-01-02")
		hour := currentTime.Hour()

		path = path + "/" + daily
		if _, err := os.Stat(path); err != nil {
			if err := os.MkdirAll(path, os.ModePerm); err != nil {
				return
			}
		}

		filePath := path + "/" + note + "_" + strconv.Itoa(hour) + ".logs"
		file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0766)
		defer file.Close()

		if err != nil {
			return
		}
		file.WriteString(logTmp)
	}()
}

// BuildUID 用了生成uid
func BuildUID(user uint64, company int) string {
	user += 136315520
	company += 1040

	var b [6]uint8
	var uid string

	b[0] = uint8(user & 0xFF)
	b[1] = uint8(user >> 8 & 0xFF)
	b[2] = uint8(user >> 16 & 0xFF)
	b[3] = uint8(user >> 24 & 0xFF)
	b[4] = uint8(company & 0xFF)
	b[5] = uint8(company >> 8 & 0xFF)

	b[1] = int8Rev(b[1])
	b[3] = int8Rev(b[3])
	b[4] = int8Rev(b[4])

	var i uint8
	for ; i < 8; i++ {
		uid += mvToStr(b, i)
	}
	return uid
}

func int8Rev(num uint8) uint8 {
	num = ((num & 0xf0) >> 4) | ((num & 0x0f) << 4)
	num = ((num & 0xCC) >> 2) | ((num & 0x33) << 2)
	num = ((num & 0xAA) >> 1) | ((num & 0x55) << 1)
	return num
}

func mvToStr(b [6]uint8, i uint8) string {
	var s uint8
	for m := 0; m < 6; m++ {
		s = (s << 1) | (b[m] >> i & 0x1)
	}

	k := "0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm@$"

	r := string([]byte(k)[s : s+1])
	return r
}
